package core

import (
	"errors"
	"fmt"
	"github.com/xiaoqinghong/super_daemon/core/daemon"
	"github.com/xiaoqinghong/super_daemon/core/process"
	"github.com/xiaoqinghong/super_daemon/core/program"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
)

var mDaemon *daemonImpl
var once = sync.Once{}

type daemonImpl struct {
	mux      sync.Mutex
	programs map[string]process.IProcess
}

func init() {
	once.Do(func() {
		mDaemon = &daemonImpl{
			programs: map[string]process.IProcess{},
		}
	})
}

func Instance() daemon.IDaemon {
	return mDaemon
}

//执行一个program转换为一个process
func (d *daemonImpl) ExecProgram(program program.IProgram) error {
	p := d.GetProcess(program.GetName())
	if p != nil {
		return errors.New(fmt.Sprintf("%s is exist", program.GetName()))
	}
	info := &process.Info{
		Name:          program.GetName(),
		User:          program.GetUser(),
		Cmd:           program.GetCmd(),
		StdoutErrFile: program.GetStdoutErrFile(),
		StdoutLogFile: program.GetStdoutLogFile(),
		Status:        process.Stopped,
	}
	cmdArr := strings.Split(info.Cmd, " ")
	cmd := &exec.Cmd{
		Path: cmdArr[0],
		Args: cmdArr,
	}
	if filepath.Base(cmd.Path) == cmd.Path {
		if lp, err := exec.LookPath(cmd.Path); err != nil {
			return err
		} else {
			cmd.Path = lp
		}
	}
	p = newProcess(cmd, info)
	d.mux.Lock()
	d.programs[program.GetName()] = p
	d.mux.Unlock()
	return d.ExecProcess(p)
}

func (d *daemonImpl) ExecProcess(process process.IProcess) error {
	return process.Run()
}

func (d *daemonImpl) GetProcess(name string) (p process.IProcess) {
	d.mux.Lock()
	p = d.programs[name]
	d.mux.Unlock()
	return p
}

func (d *daemonImpl) StopProcess(process process.IProcess) error {
	return process.Stop()
}

func (d *daemonImpl) RestartProcess(process process.IProcess) error {
	return process.Restart()
}

func (d *daemonImpl) List() []process.Info {
	var list []process.Info
	for _, p := range d.programs {
		list = append(list, p.GetInfo())
	}
	return list
}
